/*
 * Copyright (c) 2022, sakumisu
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#ifndef USB_LOG_H
#define USB_LOG_H

#include "ulog.h"
#include <stdint.h>

// 日志级别映射
#define USB_DBG_ERROR   ULOG_ERROR_LEVEL
#define USB_DBG_WARNING ULOG_WARNING_LEVEL
#define USB_DBG_INFO    ULOG_INFO_LEVEL
#define USB_DBG_LOG     ULOG_DEBUG_LEVEL

#ifndef USB_DBG_TAG
#define USB_DBG_TAG "USB"
#endif

// 定义LOG_TAG供uLog使用
#undef LOG_TAG
#define LOG_TAG USB_DBG_TAG

/*
 * The color for terminal (foreground)
 * BLACK    30
 * RED      31
 * GREEN    32
 * YELLOW   33
 * BLUE     34
 * PURPLE   35
 * CYAN     36
 * WHITE    37
 */

// 重定义日志宏以适配uLog
#if (LOG_ENABLE && (LOG_LEVEL_INFO >= USB_DBG_LOG))
#define USB_LOG_DBG(fmt, ...) ULOG_TAG_DEBUG(fmt, ##__VA_ARGS__)
#else
#define USB_LOG_DBG(...)
#endif

#if (LOG_ENABLE && (LOG_LEVEL_INFO >= USB_DBG_INFO))
#define USB_LOG_INFO(fmt, ...) ULOG_TAG_INFO(fmt, ##__VA_ARGS__)
#else
#define USB_LOG_INFO(...)
#endif

#if (LOG_ENABLE && (LOG_LEVEL_INFO >= USB_DBG_WARNING))
#define USB_LOG_WRN(fmt, ...) ULOG_TAG_WARNING(fmt, ##__VA_ARGS__)
#else
#define USB_LOG_WRN(...)
#endif

#if (LOG_ENABLE && (LOG_LEVEL_INFO >= USB_DBG_ERROR))
#define USB_LOG_ERR(fmt, ...) ULOG_TAG_ERROR(fmt, ##__VA_ARGS__)
#else
#define USB_LOG_ERR(...)
#endif

#define USB_LOG_RAW(...) ULOG_RAW(__VA_ARGS__)

#ifndef CONFIG_USB_ASSERT_DISABLE
#define USB_ASSERT(f)                                                            \
    do {                                                                         \
        if (!(f)) {                                                              \
            USB_LOG_ERR("ASSERT FAIL [%s] @ %s:%d\r\n", #f, __FILE__, __LINE__); \
            while (1) {                                                          \
            }                                                                    \
        }                                                                        \
    } while (false)

#define USB_ASSERT_MSG(f, fmt, ...)                                              \
    do {                                                                         \
        if (!(f)) {                                                              \
            USB_LOG_ERR("ASSERT FAIL [%s] @ %s:%d\r\n", #f, __FILE__, __LINE__); \
            USB_LOG_ERR(fmt "\r\n", ##__VA_ARGS__);                              \
            while (1) {                                                          \
            }                                                                    \
        }                                                                        \
    } while (false)
#else
#define USB_ASSERT(f) {}
#define USB_ASSERT_MSG(f, fmt, ...) {}
#endif

#define ___is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
static inline void usb_hexdump(const void *ptr, uint32_t buflen)
{
    unsigned char *buf = (unsigned char *)ptr;
    unsigned int i, j;

    (void)buf;

    for (i = 0; i < buflen; i += 16) {
        ULOG_RAW("%08x:", i);

        for (j = 0; j < 16; j++)
            if (i + j < buflen) {
                if ((j % 8) == 0) {
                    ULOG_RAW("  ");
                }

                ULOG_RAW("%02X ", buf[i + j]);
            } else
                ULOG_RAW("   ");
        ULOG_RAW(" ");

        for (j = 0; j < 16; j++)
            if (i + j < buflen)
                ULOG_RAW("%c", ___is_print(buf[i + j]) ? buf[i + j] : '.');
        ULOG_RAW("\n");
    }
}

#endif /* USB_LOG_H */